﻿using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using SharpDX;

namespace RPGOnlineWPF.Renderer
{
	public abstract class SceneBase<T> : BaseInteractive<T> //, IDisposable
		where T : D3D
	{
		/// <summary>
		/// 
		/// </summary>
		private T m_context;

		protected List<BaseInteractive<T>> m_children = new List<BaseInteractive<T>>();
		protected IEnumerable<BaseInteractive<T>> Children
		{
			get { return m_children; }
		}

		public void AddChild(BaseInteractive<T> child)
		{
			if (Renderer != null)
				child.Renderer = Renderer;
			m_children.Add(child);
		}

		public void RemoveChild(BaseInteractive<T> child)
		{
			child.Renderer = null;
			m_children.Remove(child);
		}

		public int Count
		{
			get { return m_children.Count; }
		}

		/// <summary>
		/// 
		/// </summary>
		public override T Renderer
		{
			get { return m_context; }
			set
			{
				if (Renderer != null)
				{
					Renderer.Rendering -= ContextRendering;
					Detach();
				}
				m_context = value;
				m_children.ForEach(c => c.Renderer = value);
				if (Renderer != null)
				{
					Renderer.Rendering += ContextRendering;
					Attach();
				}
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public override void Attach()
		{
			m_children.ForEach(c => c.Attach());
		}

		/// <summary>
		/// 
		/// </summary>
		public override void Detach()
		{
			m_children.ForEach(c => c.Detach());
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="args"></param>
		public override void Reset(DrawEventArgs args)
		{
			if (Renderer != null)
				Renderer.Reset(args);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="args"></param>
		public override void Render(DrawEventArgs args)
		{
			if (Renderer != null)
				Renderer.Render(args);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="aCtx"></param>
		/// <param name="args"></param>
		private void ContextRendering(object aCtx, DrawEventArgs args) { RenderScene(args); }


		
	}

	public abstract class BaseInteractive<T> : IInteractiveDirect3D
		where T : D3D
	{
		public abstract T Renderer { get; set; }
		public bool Selected { get; set; }

		public abstract void Attach();
		public abstract void Detach();
		public abstract void RenderScene(DrawEventArgs args);

		public virtual void OnMouseDown(UIElement ui, MouseButtonEventArgs e)
		{
			Renderer.OnMouseDown(ui, e);
		}

		public virtual void OnMouseMove(UIElement ui, MouseEventArgs e)
		{
			Renderer.OnMouseMove(ui, e);
		}

		public virtual void OnMouseUp(UIElement ui, MouseButtonEventArgs e)
		{
			Renderer.OnMouseUp(ui, e);
		}

		public virtual void OnMouseWheel(UIElement ui, MouseWheelEventArgs e)
		{
			Renderer.OnMouseWheel(ui, e);
		}

		public virtual void OnKeyDown(UIElement ui, KeyEventArgs e)
		{
			Renderer.OnKeyDown(ui, e);
		}

		public virtual void OnKeyUp(UIElement ui, KeyEventArgs e)
		{
			Renderer.OnKeyUp(ui, e);
		}

		public abstract void Reset(DrawEventArgs args);
		public abstract void Render(DrawEventArgs args);
	}
}